Skip to content

fix(deps): update dependency @mastra/core to v1#48

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/mastra-core-1.x
Open

fix(deps): update dependency @mastra/core to v1#48
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/mastra-core-1.x

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate Bot commented Jan 21, 2026

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
@mastra/core (source) ^0.12.1^1.0.0 age confidence

Release Notes

mastra-ai/mastra (@​mastra/core)

v1.36.0

Compare Source

Minor Changes
  • Added activateAfterIdle: "auto" for Observational Memory early activation. (#​16663)

    Mastra can now choose an idle activation timeout from the active model provider's prompt cache behavior. OpenAI also respects providerOptions.openai.promptCacheRetention when available.

    const memory = new Memory({
      options: {
        observationalMemory: {
          model: 'google/gemini-2.5-flash',
          activateAfterIdle: 'auto',
          activateOnProviderChange: true,
        },
      },
    });
  • Added support for permission arrays in FGA checks and route configuration. When an array is provided, the user needs any one of the listed permissions (logical OR). (#​16605)

    Affected types

    • FGACheckParams.permission
    • FGARouteConfig.permission
    • FGARouteInfo.requiresPermission
    • FGADeniedError.permission
    • CheckFGAOptions.permission

    Single-permission usage continues to work unchanged.

    // Before — single permission only
    await fga.check({
      resource: { type: 'agent', id: 'abc' },
      permission: 'agents:read',
    });
    
    // After — single permission or array (ANY-of)
    await fga.check({
      resource: { type: 'agent', id: 'abc' },
      permission: ['agents:read', 'agents:execute'],
    });
  • Added consistent FGA execution checks across agents, tools, memory, and workflows to prevent unauthenticated executions when FGA is configured. Pass an authenticated user through requestContext when invoking protected APIs directly: (#​16651)

    const requestContext = new RequestContext();
    requestContext.set('user', user);
    
    await agent.generate('Summarize this thread', {
      requestContext,
    });
  • Added the EditorFavorite* types and an optional favorites namespace on IMastraEditor so editor implementations can expose favoriting of stored agents and skills. (#​16749)

    import type {
      IMastraEditor,
      IEditorFavoritesNamespace,
      EditorFavoriteTargetInput,
      EditorFavoriteToggleResult,
    } from '@​mastra/core/editor';
    
    interface IMastraEditor {
      // ...existing members...
      favorites?: IEditorFavoritesNamespace;
    }

    The favorites field is optional — existing implementations of IMastraEditor continue to work unchanged. @mastra/editor ships a default EditorFavoritesNamespace that wires this up against the storage favorites domain.

    Also renamed AgentFeatures.stars to AgentFeatures.favorites in @mastra/core/agent-builder/ee so the feature flag aligns with the storage column (favoriteCount), HTTP routes (/favorite), and the editor favorites namespace. The field had no functional consumers, so this is a name-only change.

  • Enterprise edition now automatically captures PostHog telemetry for EE license checks and feature usage, including license validation status, RBAC access resolution, FGA authorization calls, and EE feature invocation metadata. Telemetry is enabled by default for EE customers and can be disabled with MASTRA_TELEMETRY_DISABLED=1; community users are unaffected. (#​16660)

  • Added new editor configuration primitives for browser providers, agent builder integration, and stored-agent visibility. (#​16778)

    New: BrowserProvider interface

    Implement a browser provider to expose browser automation tools to agents via the editor. Each provider declares an id, name, and config schema, then returns a MastraBrowser instance from createBrowser.

    import type { BrowserProvider } from '@​mastra/core/editor';
    
    const myProvider: BrowserProvider = {
      id: 'my-browser',
      name: 'My Browser',
      description: 'Custom browser automation',
      configSchema: z.object({ apiKey: z.string() }),
      createBrowser: async config => {
        return createMyBrowser(config.apiKey);
      },
    };

    New: MastraEditorConfig.browsers and .builder

    Wire browser providers and agent-builder options into the editor:

    new MastraEditor({
      browsers: { 'my-browser': myProvider },
      builder: { features: { agent: { favorites: true } } },
    });

    New: visibility on updateAgentMeta

    Set an agent's visibility (private or public) through the editor namespace:

    await editor.agent.updateAgentMeta('agent-id', { visibility: 'public' });
  • publishSkill now returns the full skill file tree so consumers can persist the UI-facing tree alongside storage blobs without re-walking the source. (#​16666)

    import { publishSkill } from '@​mastra/core/workspace';
    
    const result = await publishSkill({ workspace, skillId, source });
    
    // New: nested tree of folders + files; binary content base64-encoded.
    for (const node of result.files) {
      console.log(node.type, node.path);
    }

    Also added two optional capability methods to IMastraEditor for server-side gating of builder-aware behavior:

    interface IMastraEditor {
      // ...existing members...
      hasEnabledBuilderConfig?(): boolean;
      resolveBuilder?(): Promise<IAgentBuilder | undefined>;
    }

    Both methods are optional — existing implementations of IMastraEditor continue to work unchanged. Servers that consume them treat undefined / missing implementation as "no builder configured."

  • Added route-specific CORS configuration so credentialed cross-origin access can be limited to selected custom routes and channel webhooks. (#​16689)

    registerApiRoute('/customer-webhook', {
      method: 'POST',
      cors: {
        origin: ['https://customer-saas.example'],
        credentials: true,
      },
      handler: async c => c.json({ ok: true }),
    });
    new Agent({
      id: 'support-agent',
      name: 'Support Agent',
      instructions: '...',
      model,
      channels: {
        adapters: {
          web: {
            adapter: createWebAdapter(),
            cors: {
              origin: ['https://customer-saas.example'],
              credentials: true,
            },
          },
        },
      },
    });

    Use server.cors for one global CORS policy across the server:

    new Mastra({
      server: {
        cors: {
          origin: '*',
        },
      },
    });
  • Narrowed AgentSignalContents from BaseMessageListInput to string | (TextPart | FilePart)[]. (#​16622)

    Fixed two signal-content bugs:

    • user-message signal attributes now reach the LLM
    • multimodal non-user-message signals no longer lose file parts

    Callers that previously passed wrapped message shapes to agent.sendSignal should now pass a bare string or a bare parts array.

    Before:
    { type: 'user-message', contents: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }] }

    After:
    { type: 'user-message', contents: [{ type: 'text', text: 'hi' }] }

    Added an optional providerOptions field to agent.sendSignal that flows through to the resulting prompt turn (as providerOptions on the LLM message) and is persisted on the stored signal message (as content.providerMetadata).

  • publishSkillFromSource() (and collectSkillForPublish()) now return a files field containing the full skill source as a tree of StorageSkillFileNode entries with base64-encoded blob content — handy for storing a UI-facing copy of a skill alongside its content-addressable tree: (#​16673)

    const { snapshot, tree, files } = await publishSkillFromSource({ source });
    // files: StorageSkillFileNode[] — name, mimeType, base64 content per node

    Existing callers that only destructure { snapshot, tree } are unaffected; the field is additive.

    Also adds parseSkillSnapshotFromFiles() for parsing skill snapshot frontmatter from a flat file list (used by the registry install flow):

    import { parseSkillSnapshotFromFiles, type SkillSnapshotFile } from '@&#8203;mastra/core/workspace';
    
    const files: SkillSnapshotFile[] = [{ path: 'SKILL.md', content: '...' }, ...];
    const snapshot = parseSkillSnapshotFromFiles(files);
  • Added delta polling support for observability list APIs in core, DuckDB, and ClickHouse. (#​16632)

Patch Changes
  • Update provider registry and model documentation with latest models and providers (452036a)

  • Fixed task_update to auto-demote previously in_progress tasks instead of returning an error when moving another task to in_progress. (#​16843)

  • Fixed durable agents to honor activeTools when streaming. (#​16646)

  • Fixed type error when a tool calls suspend(...) inside execute while also declaring an outputSchema. The execute return type now allows void in addition to the declared output shape, so the idiomatic return await suspend(...) pattern type-checks correctly. (#​16799)

  • Fixed a startup bug in MastraCompositeStore.init() when using default or editor. (#​16786)

    Before this fix, the composite initialized inner domains directly and could skip parent store initialization. That could skip adapter setup steps and cause missing-table errors during startup (most visibly with LibSQLStore on a local file).

    Now, MastraCompositeStore.init() runs parent default and editor initialization first, then initializes only domains not already covered by those parents. This preserves adapter-specific initialization behavior and prevents startup races.

    Fixes #​16782.

  • Fixed CompositeAuth incorrectly advertising SSO, session, and user provider capabilities when no inner provider supports them. Studio would show an SSO login button even when no provider had SSO configured, leading to 401 errors on login attempts. The duck-typing check now verifies that interface methods are actual functions rather than just present on the prototype chain. (#​16664)

  • Hide internal workflow spans from Mastra-owned plumbing in exported traces. (#​16631)

  • Channels now serialize messages per thread to keep conversations in order, and the tool approval flow is fixed end-to-end: (#​16517)

    • Messages arriving while the agent is busy are delivered into the running agent loop instead of starting a new, conflicting stream on the same thread. Each Mastra thread shares one subscription, and channel/author facts (platform, message id, author name) are surfaced on the stored message under providerMetadata.mastra.channels.<platform>.
    • Tool approval flow: approving now drains the resumed run so the card is updated with the tool result and any follow-up assistant text is posted. Denying now resumes the run via declineToolCall instead of leaving it suspended. agent.subscribeToThread() consumers also receive chunks from resumed runs (the subscription used to drop the second registration for a resumed run that kept its original runId).
    • The original ChannelConfig is now exposed via the new AgentChannels.channelConfig field so channel providers can merge with existing adapters instead of replacing them.
    • Bumped chat to ^4.29.0.
  • Added the internalUsage?: UsageStats field to AIBaseAttributes, so any span type can carry token usage rolled up from internal descendant spans. Populated automatically by @mastra/observability when an internal MODEL_GENERATION ends inside a non-internal ancestor. (#​16434)

  • Fixed trajectory scorers so tool calls stored only in V2 content.parts are included in extracted eval steps. (#​15439)

  • Fixed thread metadata updates to merge with existing fields instead of replacing them. Previously, updating a thread's metadata would silently drop any fields not included in the update. Now existing metadata fields are preserved when updating. (#​16846)

    Fixed MockMemory working memory tool to support partial JSON updates when using schema-based working memory. Previously, sending a partial update would overwrite all existing data. Now for schema-based configs, unchanged fields are preserved automatically (matching @​mastra/memory behavior).

    Fixed MockMemory constructor to preserve workingMemory config options (like schema) when enableWorkingMemory is true.

  • Improved MastraCode quiet mode so terminal sessions are easier to scan. (#​16771)

    • Quiet mode is now the default for new installs, and existing classic users get a one-time prompt to choose whether to enable it.
    • Added compact tool previews with a configurable preview-line limit, including an option to hide previews.
    • Improved repeated tool-call rendering, path continuation handling, task wrapping, shell/error previews, and spacing between tools, messages, plans, and completed subagents.
    • Added edited line ranges to workspace edit results so tool UIs can show where replacements happened.
  • Remove hardcoded /api/ prefix check from registerApiRoute(). The check incorrectly rejected custom routes starting with /api/ even when users configured a different apiPrefix. Reserved-path validation is already handled at the server adapter level using the actual configured prefix. (#​16859)

  • Fixed infinite recursion in RequestContext.toJSON() when multiple (#​16686)
    RequestContext instances reference each other through stored values.
    Previously, serializing such cross-context cycles would cause a CPU hang.
    Cyclic references are now detected and omitted from the serialized output,
    consistent with how circular references within a single context are handled.

  • Fixed crash in CacheKeyGenerator.fromAIV4Part when a tool-invocation part has undefined toolInvocation. This can happen when observational memory seals a partially-streamed assistant message. Also guarded MessageMerger against the same condition. (#​16773)

  • Agent signals can now coordinate active thread runs across agents that share a PubSub instance, so thread subscribers and signal senders can observe the same run instead of being limited to one runtime instance. (#​16665)

    import { Agent } from '@&#8203;mastra/core/agent';
    import { EventEmitterPubSub } from '@&#8203;mastra/core/events';
    
    const pubsub = new EventEmitterPubSub();
    const agent = new Agent({
      id: 'agent',
      name: 'Agent',
      instructions: 'Help the user',
      model,
      pubsub,
    });
  • Exposed formatSkillActivation(skill) from @mastra/core/workspace. It returns the activation payload — instructions plus references, scripts, and assets listings — that the built-in skill tool uses, so callers (e.g. an explicit /skill/<name> slash command) can produce the same output without duplicating the formatting logic. (#​16618)

    Also preserves the user-invocable skill frontmatter field in workspace skill metadata.

    import { formatSkillActivation } from '@&#8203;mastra/core/workspace';
    
    const content = formatSkillActivation(skill);
  • Fixed sub-agent streams so nested tool input progress is emitted while tool arguments are still being generated. This lets UIs show delegated agents preparing tool calls before the final tool input is available. Fixes #​16422. (#​16553)

  • Fixed backgroundTasks: { enabled: true } silently dispatching foreground-only tools to the background. (#​16792)

    Previously, enabling backgroundTasks on the Mastra instance injected a system prompt into every agent that taught the LLM to flip any tool to background by passing _background: { enabled: true } in its arguments, and the resolver honored that override unconditionally. Models would readily do this for short, deterministic tools — a plain calculator could return "Background task started…" instead of { result: 42 }, breaking agent.generate() / agent.stream() for tool-using flows.

    The LLM _background override is now treated as a modifier on tools the developer has opted in at the tool or agent layer, not a standalone opt-in. If a tool hasn't been opted in via tool-level background: { enabled: true } or agent-level backgroundTasks: { tools: { … } } (or tools: 'all'), _background.enabled: true from the model is ignored and the tool runs in the foreground. Opted-in tools continue to honor LLM overrides for enabled, timeoutMs, and maxRetries as documented.

    Fixes #​16783

  • Fixed scheduler performance and correctness issues that could cause excessive Postgres CPU and noisy failed runs. (#​16805)

    • Added missing indexes on the schedules tables that the tick loop polls every 10 seconds: (status, next_fire_at) on mastra_schedules and (schedule_id, actual_fire_at) on mastra_schedule_triggers. Without these the scheduler performed a full sequential scan on every tick.
    • The scheduler tick loop is now only started when at least one workflow declares a schedule (or scheduler.enabled is set explicitly), so deployments without scheduled workflows no longer poll the database at all.
    • The scheduler now validates that a schedule's target workflow is still registered before firing it. Schedules whose target workflow has been removed from the Mastra config are skipped for a short grace window and then deleted, so stale rows stop producing failed workflow runs forever.
    • The scheduler is now lazily initialized inside startWorkers(). Accessing mastra.scheduler before startWorkers() runs throws a descriptive error instead of returning a half-initialized instance.
  • Fixed Mastra getting stuck after a storage startup failure. Previously, if storage couldn't start up (for example, because the database was briefly unreachable), Mastra would keep returning the same error for every operation until the process was restarted. Now the next storage operation tries to start storage again, so brief outages recover on their own. Storage startup failures are also logged, so the problem is visible even when a later retry succeeds. (#​16427)

  • Restore MastraCode local command execution to inherit parent environment variables while redacting env-shaped and secret-looking workspace trace data. (#​16691)

  • Added a Unix socket PubSub transport and wired the Mastra Code TUI through a per-resource socket so local sessions can coordinate thread streams across processes. Programmatic createMastraCode usage remains opt-in: (#​16669)

    await createMastraCode({ unixSocketPubSub: true });
  • Fix in-memory observability storage to match the contract validated against DuckDB/ClickHouse vNext adapters. (#​16808)

    Previously, when running Mastra with the default in-memory storage, several observability operations behaved differently than they would against a production database:

    • getSpans threw 'This storage provider does not support batch-fetching spans'. It now batch-fetches spans by id within a trace, enabling the optimized getBranch path on in-memory storage.
    • batchCreateLogs, batchCreateMetrics, createScore/batchCreateScores, createFeedback/batchCreateFeedback appended duplicate records on retry. They now upsert by id, preserving the cursor id so delta polling does not re-emit the record. This makes client retries safe.
    • Discovery operations (getEntityTypes, getEntityNames, getServiceNames, getEnvironments, getTags) only inspected spans. They now also scan logs and metrics, so dimensions emitted on those surfaces are surfaced in discovery results.
    • getMetricTimeSeries merged grouped series whose label values contained the | character (e.g. {segmentA: 'a', segmentB: 'b|c'} collided with {segmentA: 'a|b', segmentB: 'c'}). Series are now keyed on the original label tuple, so colliding display names remain distinct series.

v1.35.0

Compare Source

Minor Changes
  • Added FGA route policy coverage controls, built-in resource route metadata resolution, and resolver hooks. (#​16485)

    For example:

    import { MastraFGAWorkos } from '@&#8203;mastra/auth-workos';
    import type { FGARouteConfig, FGARouteResolver, IFGAProvider } from '@&#8203;mastra/core/auth/ee';
    import { createRoute } from '@&#8203;mastra/server/server-adapter';
    
    const routeFGA = {
      'GET /billing/:accountId': {
        resourceType: 'account',
        resourceIdParam: 'accountId',
        permission: 'billing:read',
      },
    } satisfies Record<string, FGARouteConfig>;
    
    const resolveRouteFGA: FGARouteResolver = ({ route }) => routeFGA[`${route.method} ${route.path}`];
    
    const fga: IFGAProvider = new MastraFGAWorkos({
      apiKey: process.env.WORKOS_API_KEY!,
      clientId: process.env.WORKOS_CLIENT_ID!,
      requireForProtectedRoutes: true,
      auditProtectedRoutes: 'warn',
      resolveRouteFGA,
      validatePermissions: async permissions => {
        /* validate mappings */
      },
    });
    
    export const getProjectRoute = createRoute({
      method: 'GET',
      path: '/projects/:projectId',
      responseType: 'json',
      requiresAuth: true,
      fga: {
        resourceType: 'project',
        resourceIdParam: 'projectId',
        permission: 'projects:read',
      },
      handler: async () => {
        return { project: null };
      },
    });
  • Added a favorites storage domain that lets users mark stored agents and skills as favorites, plus visibility ('private' | 'public') and favoriteCount fields on stored agents and skills so callers can list, filter, and order by favorite state. (#​16580)

    Existing rows without visibility or favoriteCount continue to work; the new fields and APIs are opt-in.

    Example

    const favorites = await storage.getStore('favorites');
    
    await favorites?.favorite({ userId: 'u1', entityType: 'agent', entityId: 'agent-123' });
    
    const favoritedIds = await favorites?.listFavoritedIds({ userId: 'u1', entityType: 'agent' });
    
    // List agents the user has favorited, surfaced first
    const { agents } = await storage.getStore('agents').list({
      pinFavoritedFor: 'u1',
      favoritedOnly: true,
    });
Patch Changes
  • Update provider registry and model documentation with latest models and providers (b661349)

  • Fixed a workspace PATCH bug in the inmemory workspace adapter: omitted config fields in a PATCH no longer overwrite previously-persisted values with undefined. (#​16580)

  • Fixed active signals so they stay in the correct order when conversations are reloaded from memory. (#​16623)

  • Fixed scheduled workflows created from the public @​mastra/core/workflows entry point so declared schedules are applied correctly. (#​16637)

  • Fixed a crash when importing @mastra/core/workflows/workflow from tests or apps, which previously failed with TypeError: Class extends value undefined is not a constructor or null (caused by a circular ESM import through the workflows barrel). (#​16661)

v1.34.0

Compare Source

Minor Changes
  • You can now run ACP-compatible coding agents as Mastra tools or lightweight subagents. ACP agents support incremental response streaming and can be used anywhere Mastra accepts a SubAgent, including supervisor delegation and workflow steps. (#​16423)

    import { createACPTool, AcpAgent } from '@&#8203;mastra/acp';
    
    export const codingTool = createACPTool({
      id: 'coding-agent',
      command: 'my-acp-agent',
    });
    
    export const codingAgent = new AcpAgent({
      id: 'coding-agent',
      command: 'my-acp-agent',
    });

    You can also wire an AcpAgent into a supervisor or workflow as a SubAgent-compatible implementation:

    import { Agent } from '@&#8203;mastra/core/agent';
    
    export const supervisor = new Agent({
      name: 'supervisor',
      instructions: 'Delegate coding tasks to the ACP agent.',
      model,
      agents: {
        codingAgent,
      },
    });

    Workflows and the Inngest workflow adapter now recognize SubAgent-compatible implementations when creating agent-backed workflow steps.

  • Added optional metadata to code-defined agents. Pass a metadata record to new Agent({...}), read it back with agent.getMetadata(), and clients can filter on it from the existing /agents and /agents/:agentId responses without encoding the data into IDs or names. (#​16603)

    Metadata supports the same DynamicArgument form as other agent config fields, so it can also be resolved per request from the request context.

    Stored agents loaded via the editor also expose their metadata through agent.getMetadata(), so clients can filter these agents as well. Cloning a runtime agent via editor.agent.clone() now carries the source agent's metadata over to the stored clone when the caller does not provide one explicitly.

    // Static
    const supportAgent = new Agent({
      id: 'support-agent',
      name: 'Support Agent',
      instructions: 'You help customers with support requests.',
      model: 'openai/gpt-5',
      metadata: { type: 'support' },
    });
    
    supportAgent.getMetadata(); // { type: 'support' }
    
    // Dynamic
    const tenantAgent = new Agent({
      id: 'tenant-agent',
      name: 'Tenant Agent',
      instructions: 'You help customers with tenant-specific tasks.',
      model: 'openai/gpt-5',
      metadata: ({ requestContext }) => ({
        type: 'support',
        tenant: requestContext.get('tenant'),
      }),
    });
    
    await tenantAgent.getMetadata({ requestContext }); // { type: 'support', tenant: 'acme' }
  • Added an opt-in foundation for building agent-builder admin policies and role-aware capabilities, available under two new entry points. (#​16578)

    @mastra/core/agent-builder/ee

    Exposes types, validators, and picker utilities for working with model allowlists and admin model policies on stored agents — for example normalizing model candidates, choosing a default from a configured allowlist, and producing typed errors when a request violates policy.

    @mastra/core/auth/ee

    Adds optional methods on IRBACProvider for listing available roles and resolving the permissions for a given role:

    interface IRBACProvider {
      // existing methods...
      getAvailableRoles?(): Promise<RoleDescriptor[]>;
      getPermissionsForRole?(role: string): Promise<PermissionDescriptor[]>;
    }

    Static defaults, an expanded permissions catalog, and a capabilities helper that surfaces availableRoles to clients when the provider supports it are also included. Providers that do not implement the new methods continue to work unchanged.

    Also adds a StorageBrowserRef shape to @mastra/core/storage for referencing a configured headless browser on stored agents.

  • Improved how the workspace read_file tool returns files to the model. Reads now branch on file type: (#​16570)

    1. Media files (default: image/png, image/jpeg, image/webp, application/pdf) are surfaced as native file/image parts the model can directly view, instead of being dumped as base64 text. Capped at 10 MiB by default so large media don't get base64-encoded into context and persisted in storage — configurable via maxMediaBytes.
    2. Text-readable files (anything text/*, common code/config mime types, or unknown extensions) are returned as text content as before.
    3. Unsupported binaries (e.g. image/png when mediaTypes is disabled, application/zip, oversized media, etc.) now return a short metadata description (path, size, mime type) instead of dumping useless base64 into the conversation. Pass an explicit encoding to opt back into the raw base64/hex dump.

    The set of mime types treated as native media parts and the inline size cap are configurable per workspace:

    import { Workspace, WORKSPACE_TOOLS } from '@&#8203;mastra/core/workspace';
    
    const workspace = new Workspace({
      filesystem,
      tools: {
        [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: {
          // Broaden to any image (e.g. SVG, BMP, HEIC) — may fail on some providers
          mediaTypes: ['image/*', 'application/pdf'],
    
          // Raise the inline-media cap to 25 MiB
          maxMediaBytes: 25 * 1024 * 1024,
    
          // Or a custom predicate
          // mediaTypes: (mime) => mime.startsWith('image/'),
    
          // Or disable media parts entirely
          // mediaTypes: false,
        },
      },
    });

    The default mediaTypes is intentionally the cross-provider-safe intersection — formats universally supported across Anthropic, OpenAI, and Gemini.

  • Changed background process output retention. (#​16574)

    Before: Spawned process handles retained all stdout and stderr, which could grow without bound for long-running background processes.

    After: Spawned process handles now retain the latest 1 MiB of stdout and stderr per stream by default. Pass maxRetainedBytes to processes.spawn() to customize the limit, use 0 to disable retained polling output, or use Infinity to keep the previous retain-all behavior.

    const handle = await sandbox.processes.spawn('npm run dev', {
      maxRetainedBytes: 512 * 1024,
    });

    Streaming callbacks and reader streams still receive every chunk in full. Handles also expose truncation and dropped-byte counters so callers can detect when stdout, stderr, or wait() results only include retained output.

    The built-in executeCommand() implementation still retains full output by default; pass maxRetainedBytes there only when you want bounded command results.

Patch Changes
  • Update provider registry and model documentation with latest models and providers (784ad98)

  • Improved background-task observability. (#​16590)

    Retry attempts now appear as separate workflow steps in run history and event traces, making retry progression easier to debug. No public API changes.

  • Fixed approval resume for tools loaded by processor workflows. (#​16365)

  • Fixed durable agents that could drop object-form system instructions when provider options like cacheControl were used. These instructions are now preserved so provider-specific options are respected. (#​16599)

  • Fixed approval resume for tools loaded with ToolSearchProcessor. (#​16365)

  • Fixed listMessages perPage=0 behavior in the in-memory store to match other adapters. (#​16602)

  • Fixed non-deterministic ordering of cross-thread semantic recall messages. (#​16600)

    When messages recalled from other threads shared the same timestamp, they were rendered into the system prompt in whatever order the vector query returned them — driven by similarity scores that can vary between equivalent runs. This made any test or evaluation that snapshots prompt output (or hashes the outbound LLM request) flaky.

    Recalled cross-thread messages are now sorted by createdAt, then threadId, then role (user → assistant → tool → system), then id before formatting, so the same set of recalled messages always produces the same prompt.

  • Expose GET /observability/traces/light and storage support for fetching paginated trace-list rows without span payload data. (#​16608)

  • GET /api/observability/discovery/metric-names and GET /api/observability/discovery/metric-label-values now accept limit as a URL query parameter without pre-parsing. Previously, passing ?limit=10 was rejected as a validation error; callers can now use these endpoints directly from HTTP clients, consistent with other query endpoints (e.g. pagination). (#​16489)

  • Fixed agent signals so standalone agents coordinate thread streams through a shared runtime. (#​16581)

v1.33.1

Compare Source

Patch Changes
  • Update provider registry and model documentation with latest models and providers (6ba46dc)

  • Fixed a bug where clicking Approve on a plan from /plan mode would show the system reminder twice and sometimes hang instead of starting build execution. Approving now reliably triggers the build agent with a single reminder. (#​16521)

  • Added (#​16520)
    You can now call run.restart() for evented workflows to continue execution from the latest persisted run state.

    const run = workflow.createRun();
    await run.start({ inputData: { jobId: 'job-123' } });
    
    // Later, restart the same run from the last active step
    await run.restart();

v1.33.0

Compare Source

Minor Changes
  • Added processLLMRequest, a processor hook that runs after messages are converted to the provider-facing prompt and before the model request is sent. The hook lets processors make temporary, model-aware prompt changes without mutating stored message history, memory, UI history, or later provider calls. (#​16176)

    ProviderHistoryCompat now uses this hook to prevent reasoning-history incompatibilities when switching providers. It strips reasoning parts from Cerebras-bound prompts that would otherwise be sent as rejected reasoning_content, and strips non-Anthropic reasoning from Anthropic-bound prompts while preserving Anthropic-native thinking blocks.

  • Improved Harness support for Agent thread signals. (#​16231)

    Harness thread subscriptions now own stream processing for followed runs, echo user-message signal data with stable IDs, and support idle signal starts without delaying optimistic rendering.

    const { id, accepted } = harness.sendSignal({
      type: 'user-message',
      contents: 'Follow up while the agent is still streaming',
    });
    await accepted;
  • Added target-aware tool payload transforms for display streams and transcript messages. Tool authors can transform tool input, output, errors, approval payloads, and suspension payloads without changing raw runtime behavior or toModelOutput. See #​16054. (#​16103)

    Use transform on tools, agents, Mastra, or individual generation calls to configure these payload transforms. Runtime callers using the previous toolPayloadProjection shape continue to be normalized for compatibility.

    const lookupCustomer = createTool({
      execute: async ({ customerId, internalPath }) => lookupCustomerRecord(customerId, internalPath),
      transform: {
        display: {
          input: ({ input }) => ({ customerId: input?.customerId }),
          output: ({ output }) => ({ displayName: output?.displayName }),
        },
        transcript: {
          input: ({ input }) => ({ customerId: input?.customerId }),
          output: ({ output }) => ({ displayName: output?.displayName }),
        },
      },
    });
  • Added Azure OpenAI Responses API and v1 routing controls. (#​16246)

    Use useResponsesAPI: true to resolve Azure deployments through the Responses API with the Azure v1 route by default:

    new AzureOpenAIGateway({
      resourceName: 'my-openai-resource',
      apiKey: process.env.AZURE_API_KEY!,
      useResponsesAPI: true,
      deployments: ['my-gpt-5-4-deployment'],
    });

    When useDeploymentBasedUrls: false is used directly, the gateway now defaults apiVersion to "v1" to match the AI SDK Azure provider's v1 URL route. Passing apiVersion: "v1" by itself keeps the existing deployment-based URL default for compatibility.

  • Mastra Eval results are now emitted once through the unified observability score pipeline. (#​16185)

  • Added Azure OpenAI Responses WebSocket transport support for streaming agent and tool loops. (#​16246)

    Configure the Azure gateway with useResponsesAPI: true, then opt into WebSocket streaming per request:

    const stream = await agent.stream('Review this task', {
      providerOptions: {
        azure: {
          transport: 'websocket',
          websocket: { closeOnFinish: false },
        },
      },
    });

    Responses WebSocket streams now preserve transport handles through agent loops, reuse explicit API-key router connections safely, clean up cancelled streams, and reject overlapping previous_response_id continuations on the same connection.

  • Added preserveModelOutput to ToolCallFilter so filtered tool history can keep compact model-facing output without raw tool args or results. (#​16060)

    import { ToolCallFilter } from '@&#8203;mastra/core/processors';
    
    const filter = new ToolCallFilter({
      preserveModelOutput: true,
    });
  • Added a SubAgent interface for custom supervisor subagents. (#​16359)

  • Added ResponseCache input processor (#​16283)

    Cache identical LLM steps to skip the model call and replay a previously cached response. Useful for prompt templates, suggested-prompt buttons, agentic search re-asks, or guardrail LLMs that classify the same input over and over.

    Caching is opt-in: register ResponseCache explicitly on inputProcessors. There is no agent-level option — this keeps the surface small while we collect feedback on the processor API. Per-call overrides flow through RequestContext.

    import { Agent } from '@&#8203;mastra/core/agent';
    import { InMemoryServerCache } from '@&#8203;mastra/core/cache';
    import { ResponseCache } from '@&#8203;mastra/core/processors';
    
    const cache = new InMemoryServerCache();
    
    const agent = new Agent({
      name: 'Search Agent',
      instructions: 'You answer questions concisely.',
      model: 'openai/gpt-5',
      inputProcessors: [new ResponseCache({ cache, ttl: 600 })],
    });
    
    // First call: cache miss → LLM call
    await agent.generate('What is the capital of France?');
    
    // Second identical call: cache hit → no LLM call
    await agent.generate('What is the capital of France?');

    Per-call overrides via RequestContext:

    import { ResponseCache } from '@&#8203;mastra/core/processors';
    import { RequestContext } from '@&#8203;mastra/core/request-context';
    
    // Force a fresh call but still update the cache.
    await agent.stream(prompt, {
      requestContext: ResponseCache.context({ bust: true }),
    });
    
    // Or merge into an existing context.
    const ctx = new RequestContext();
    ResponseCache.applyContext(ctx, { key: 'custom-key' });
    await agent.stream(prompt, { requestContext: ctx });

    Three fields are overridable per call: key, scope, bust. cache, ttl, and agentId stay on the constructor.

    A key function receives { agentId, scope, model, prompt, stepNumber } and returns a string (or Promise<string>):

    await agent.stream(prompt, {
      requestContext: ResponseCache.context({
        key: ({ model, prompt }) => `qa:${model.modelId}:${JSON.stringify(prompt).slice(-200)}`,
      }),
    });

    The cache key is derived from the resolved prompt Mastra is about to send to the model — i.e. after memory loading and earlier input processors have run — so cached entries are tenant-isolated and don't leak context across users with shared prompts but different memory state. Each step in an agentic tool loop is independently cached. By default, the cache scope falls back to MASTRA_RESOURCE_ID_KEY from the request context for automatic per-user isolation. Failed runs (errors, tripwire activations) are not cached. See Response caching for details.

    Also adds:

    • InMemoryServerCache (in @mastra/core/cache) for local development. ResponseCache accepts any MastraServerCache directly — use RedisCache from @mastra/redis for production.
    • MastraServerCache.set() now accepts an optional ttlMs argument so implementations can override the configured default TTL on a per-entry basis. InMemoryServerCache and RedisCache (in @mastra/redis) both honor this.
    • New paired processor hooks processLLMRequest and processLLMResponse. ProcessLLMRequestResult may return { response } to short-circuit the LLM call with a cached payload.
  • Added workflow state reader helpers to inspect persisted workflow runs and recover suspended or long-running workflows. (#​16091)

    The reader exposes suspended steps, resume labels, step payloads, and step outputs from the public WorkflowState returned by workflow.getWorkflowRunById(), and WorkflowState step results now reflect foreach array entries.

  • Added Agent signals for sending contextual messages into agent thread loops and subscribing to thread activity. (#​16229)

    Call agent.sendSignal() to inject context into a running agent loop. When the thread is idle, that same signal becomes the prompt that starts the next loop by default. Use ifActive.behavior and ifIdle.behavior to deliver, persist, discard, or wake from a signal.

    Use agent.subscribeToThread() to follow the raw stream chunks for a memory thread, observe signal echoes with stable IDs, and abort the active stream for that thread.

    const subscription = await agent.subscribeToThread({ resourceId, threadId });
    
    void (async () => {
      for await (const part of subscription.stream) {
        if (part.type === 'finish') {
          subscription.unsubscribe();
        }
      }
    })();
    
    agent.sendSignal({ type: 'user-message', contents: 'Use the latest answer' }, { resourceId, threadId });
  • Add metadata filtering support to semantic recall. (#​9256)

  • Fixed Azure and OpenAI Responses item handling so multi-step reasoning and tool-call histories round-trip correctly without item ID collisions. (#​16246)

    Added provider-neutral response item helpers to @mastra/core/agent/message-list. Existing in-memory message cache entries are regenerated after upgrade.

  • Improved foreach workflow execution to keep concurrency slots filled as iterations finish. (#​12860)

  • Added processor sendSignal support and routed built-in system reminders through signal messages. (#​16438)

  • Added structured drop event types and an onDroppedEvent hook so exporters and bridge integrations can observe events dropped by the observability pipeline. (#​16111)

  • Added stable IDs to Harness task items plus task_update and task_complete for updating or completing one tracked task by ID. Task tools now return structured task snapshots, and task_check returns summary and incompleteTasks fields so agents and UIs can restore and verify task state without parsing text. (#​16254)

    Harness also exports TaskItemSnapshot, assignTaskIds, and harness.restoreDisplayTasks() for UI history replay, serializes task reads and mutations against the latest task state snapshot, and returns task-tool errors inside forked subagents so sidecar work cannot mutate parent task state.

  • Added new MODEL_INFERENCE span type under MODEL_STEP, covering only the model provider call. Use it to measure model latency separately from input/output processors and tool executions. (#​16267)

  • Added experimental support for using remote A2A agents as Mastra subagents. (#​16348)

    What changed

    • Mastra agents can register remote A2A endpoints through A2AAgent and delegate to them like other subagents.
    • Remote A2A subagents support generate, resumeGenerate, stream, and resumeStream so parent agents can use them in normal subagent flows.
    • Agent Cards can be cached and verified with pluggable verification hooks before remote execution begins.
    • Browser environments can import shared A2A types and errors from @mastra/core/a2a/client.

    Example

    import { Agent } from '@&#8203;mastra/core/agent';
    import { A2AAgent } from '@&#8203;mastra/core/a2a';
    
    const agent = new Agent({
      name: 'Support Agent',
      instructions: 'Use the remote billing specialist for billing questions.',
      model: 'openai/gpt-4o-mini',
      agents: {
        billingSpecialist: new A2AAgent({
          url: 'https://billing.example.com/.well-known/agent-card.json',
        }),
      },
    });
    
    const result = await agent.generate('Can you check the latest invoice status?');

    Why
    This lets Mastra agents compose with remote A2A agents without exposing those integrations as plain tools or depending directly on the client SDK.

  • Worker review fixes: (#​16309)

    • Step-execution endpoint (POST /workflows/:id/runs/:runId/steps/execute) is
      now gated by Mastra's standard requiresAuth: true + authenticateToken
      pipeline rather than a parallel "worker secret" body field. The previously
      introduced workerSecret config knob and MASTRA_WORKER_SECRET env var
      have been removed (they were never released). To gate the endpoint on a
      standalone-worker deployment, configure an auth provider on the server's
      Mastra instance — without one the framework currently treats
      requiresAuth: true as a no-op for this route.
    • HttpRemoteStrategy now sends credentials as a normal Authorization: Bearer <token> header. The token comes from the new
      MASTRA_WORKER_AUTH_TOKEN env var or an explicit auth constructor option.
    • Honor the caller's abortSignal in HttpRemoteStrategy by combining it
      with the per-request timeout via AbortSignal.any (with a manual fallback
      for runtimes that don't expose it).
    • Implement comma-separated name filtering for the MASTRA_WORKERS env var.
      MASTRA_WORKERS=scheduler,backgroundTasks now boots only those named
      workers; MASTRA_WORKERS=false still disables all workers.
    • Restore Mastra.startEventEngine / stopEventEngine as @deprecated
      aliases for the renamed startWorkers / stopWorkers.
    • BackgroundTaskWorker now subscribes to PubSub in start() instead of
      init(), matching the lifecycle of the other workers and making
      isRunning accurately reflect subscription state.
    • RedisStreamsPubSub adds a maxDeliveryAttempts option (default 5) that
      drops events after the configured number of failed deliveries instead of
      redelivering forever, and replaces empty catch {} blocks with
      logger.warn/logger.debug calls.
    • RedisStreamsPubSub.unsubscribe(topic, cb) now honors the topic argument
      so the same callback can be subscribed to multiple topics independently.
    • PullTransport guards the async router callback against unhandled promise
      rejections by attaching a .catch that nacks the message.
    • Drop the dead MASTRA_WORKER_NAME env var injection in the CLI worker
      spawn (the bundle entrypoint already passes the worker name directly).
    • Add a real cross-process e2e auth suite
      (pubsub/redis-streams/src/auth-e2e.test.ts) covering happy path, wrong
      token, missing token, anonymous direct hits, and the no-auth-provider
      pin-down behavior.
    • Step-execution route now has a response schema, satisfying
      schema-consistency.test.ts.
    • Internal type cleanups (drop several as any casts in worker strategies
      and BackgroundTaskWorker).
    • RedisStreamsPubSub.maxDeliveryAttempts now rejects negative / NaN values
      at construction. 0 still means "no cap" for back-compat but emits a
      one-time warning; pass Infinity to disable the cap explicitly.
    • PullTransport accepts a logger and uses it for unhandled router-callback
      rejections instead of console.error.
    • BackgroundTaskWorker.start() now throws if init() was not called,
      matching the contract of the other workers.
    • Cross-process integration tests now spawn a single user-owned project
      (test-fixtures/cli-project/src/mastra/index.ts) through two generic
      entries that mirror what BuildBundler and WorkerBundler emit. The
      previous one-off server.entry.ts / worker.entry.ts /
      scheduler.entry.ts / background.entry.ts files have been deleted —
      they implied users hand-roll entry files, which they don't. Worker role
      is selected via MASTRA_WORKERS exactly as in production.

    Push-capable PubSub:

    • The PubSub abstract class now declares a supportedModes getter
      (defaulting to ['pull'] for backward compatibility) so consumers can
      tell whether a broker delivers events through a pull loop, an in-process
      push, or an out-of-process HTTP push. EventEmitterPubSub reports
      ['pull', 'push'] (EventEmitter dispatches synchronously and works for
      either path), @mastra/redis-streams reports ['pull'].
    • Mastra now exposes a public handleWorkflowEvent(event) method backed
      by a shared WorkflowEventProcessor. It is the single entry point used
      by the existing pull-mode OrchestrationWorker, by in-process push
      pubsubs (auto-wired during startWorkers()), and by the new
      POST /api/workflows/events route which lets push-mode brokers (GCP
      Pub/Sub push, SNS, EventBridge) deliver events over HTTP.
    • When the configured pubsub does not support 'pull', Mastra
      automatically skips creating an OrchestrationWorker and
      OrchestrationWorker.init() throws a clear error if it is constructed
      against a push-only pubsub.
    • WorkflowEventProcessor gains a handle(event) method that returns a
      structured { ok, retry } result. The original process(event, ack?)
      method is preserved as a thin wrapper for back-compat.

    Public-API example for a push-capable PubSub:

    import { Mastra } from '@&#8203;mastra/core/mastra';
    import { EventEmitterPubSub } from '@&#8203;mastra/core/pubsub';
    
    const mastra = new Mastra({
      // A push-capable broker (GCP Pub/Sub push, SNS, EventEmitter, …).
      // EventEmitterPubSub reports supportedModes = ['pull', 'push'].
      pubsub: new EventEmitterPubSub(),
      workflows: { myWorkflow },
    });
    
    // In-process push pubsubs are auto-wired here. For out-of-process
    // push (e.g. HTTP webhook from a cloud broker), POST the event to
    // /api/workflows/events on your Mastra server instead.
    await mastra.startWorkers();
    
    // Direct invocation (e.g. inside an HTTP handler that bridges from a
    // cloud broker's push delivery):
    await mastra.handleWorkflowEvent({
      id: 'evt-1',
      type: 'workflow.start',
      runId: 'run-1',
      createdAt: new Date(),
      data: { workflowId: 'myWorkflow', inputData: { name: 'world' } },
    });

    CI follow-ups:

    • Mastra only auto-registers SchedulerWorker when storage is configured.
      Without storage the worker would crash on startup (deps.storage.getStore
      on undefined); the scheduler now silently no-ops in that case, matching the
      pre-worker scheduler behavior.
    • SchedulerWorker.init defensively logs and returns when called without
      storage instead of throwing a TypeError.
    • RECEIVE_WORKFLOW_EVENT_ROUTE (`POST

Note

PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch from 7b23759 to 4ca1f39 Compare January 22, 2026 07:20
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 3 times, most recently from c64fbb8 to c33d6c8 Compare February 4, 2026 22:04
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 4 times, most recently from 6ad1902 to ef06b25 Compare February 17, 2026 18:41
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 4 times, most recently from 181489a to 7f2bbe9 Compare February 26, 2026 00:51
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 4 times, most recently from 9583e0f to bf7edb0 Compare March 6, 2026 01:33
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 4 times, most recently from ee1ce1f to 877ff2d Compare March 18, 2026 05:22
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 3 times, most recently from 0eeb3ee to aad6296 Compare March 26, 2026 17:21
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 5 times, most recently from be8d060 to 3342730 Compare April 4, 2026 01:33
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 2 times, most recently from 7283845 to 351503f Compare April 8, 2026 08:36
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 4 times, most recently from 6447382 to a2ce468 Compare April 15, 2026 09:10
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 4 times, most recently from 3e0ca28 to 2121e8f Compare April 29, 2026 00:55
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 5 times, most recently from 90f71f3 to a7d4d63 Compare May 5, 2026 05:27
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch 6 times, most recently from 60ada13 to 95f67b1 Compare May 18, 2026 12:11
@renovate renovate Bot force-pushed the renovate/mastra-core-1.x branch from 95f67b1 to a41f905 Compare May 21, 2026 01:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants